package workspace;

import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import codeblocks.Block;

import controller.WorkspaceController;

import renderable.BlockUtilities;
import renderable.RenderableBlock;
import rita.settings.Language;

/**
 * ContextMenu handles all the right-click menus within the Workspace. TODO ria
 * enable customization of what menu items appear, fire events depending on what
 * items are clicked (if we enabled the first feature)
 * 
 * TODO ria still haven't enabled the right click menu for blocks
 */
public class ContextMenu extends PopupMenu implements ActionListener {
	private static final long serialVersionUID = 328149080421L;

	// context menu renderableblocks plus
	// menu items for renderableblock context menu
	private static ContextMenu rndBlockMenu = new ContextMenu();
	private static ContextMenu addCommentMenu = new ContextMenu();
	private static MenuItem addCommentItem;
	private final static String ADD_COMMENT_BLOCK = "ADDCOMMENT";
	private static boolean addCommentMenuInit = false;
	private static ContextMenu removeCommentMenu = new ContextMenu();
	private static MenuItem removeCommentItem;
	private final static String REMOVE_COMMENT_BLOCK = "REMOVECOMMENT";
	private static boolean removeCommentMenuInit = false;

	// private static boolean addCreateCallMenuInit = false;
	private static ContextMenu createCallMenu = new ContextMenu();
	private static MenuItem createCallItem;
	private final static String CREATE_CALL_BLOCK = "CREATECALL";
	// private static boolean createCallMenuInit = false;

	// private static boolean addCreateSetterMenuInit = false;
	private static ContextMenu createSetterMenu = new ContextMenu();
	private static MenuItem createSetterItem;
	private final static String CREATE_SETTER_BLOCK = "CREATESETTER";
	// private static boolean createSetterMenuInit = false;

	// private static boolean addCreateGetterMenuInit = false;
	private static ContextMenu createGetterMenu = new ContextMenu();
	private static MenuItem createGetterItem;
	private final static String CREATE_GETTER_BLOCK = "CREATEGETTER";
	// private static boolean createGetterMenuInit = false;

	// context menu for canvas plus
	// menu items for canvas context menu
	private static ContextMenu canvasMenu = new ContextMenu();
	private static MenuItem arrangeAllBlocks;
	// private static MenuItem generateCode;
	private final static String ARRANGE_ALL_BLOCKS = "ARRANGE_ALL_BLOCKS";
	private final static String GENERATE_JAVA_CODE = "GENERATE_JAVA_CODE";
	private static boolean canvasMenuInit = false;

	/** The JComponent that launched the context menu in the first place */
	private static Object activeComponent = null;

	// privatize the constructor
	private ContextMenu() {
	}

	/**
	 * Initializes the context menu for adding Comments.
	 */
	private static void initAddCommentMenu() {
		addCommentItem = new MenuItem(Language.get("addComment"));
		addCommentItem.setActionCommand(ADD_COMMENT_BLOCK);
		addCommentItem.addActionListener(rndBlockMenu);
		addCommentMenu.add(addCommentItem);
		addCommentMenuInit = true;
	}

	/**
	 * Initializes the context menu for deleting Comments.
	 */
	private static void initRemoveCommentMenu() {

		removeCommentItem = new MenuItem(Language.get("deleteComment"));
		removeCommentItem.setActionCommand(REMOVE_COMMENT_BLOCK);
		removeCommentItem.addActionListener(rndBlockMenu);

		removeCommentMenu.add(removeCommentItem);
		// rndBlockMenu.add(runBlockItem);

		removeCommentMenuInit = true;
	}

	/**
	 * Initializes the context menu for the BlockCanvas
	 * 
	 */
	private static void initCanvasMenu() {
		arrangeAllBlocks = new MenuItem(Language.get("arrangeBlocks")); // TODO
																		// some
																		// workspaces
																		// don't
																		// have
																		// pages
		arrangeAllBlocks.setActionCommand(ARRANGE_ALL_BLOCKS);
		arrangeAllBlocks.addActionListener(canvasMenu);

		canvasMenu.add(arrangeAllBlocks);
		/*
		 * //generateCode allows java code generation generateCode = new
		 * MenuItem(Language.get("generateCode")); //TODO some workspaces don't
		 * have pages generateCode.setActionCommand(GENERATE_JAVA_CODE);
		 * generateCode.addActionListener(canvasMenu);
		 * 
		 * canvasMenu.add(generateCode);
		 */

		canvasMenuInit = true;
	}

	/**
	 * Returns the right click context menu for the specified JComponent. If
	 * there is none, returns null.
	 * 
	 * @param o
	 *            JComponent object seeking context menu
	 * @return the right click context menu for the specified JComponent. If
	 *         there is none, returns null.
	 */
	public static PopupMenu getContextMenuFor(Object o) {
		if (o instanceof RenderableBlock) {
			// TODO aqui deberia ser is MethodDecl..(KIND), pero si le cambio el
			// kind de procedure no hace el abrir/cerrar el metodo

			if (((RenderableBlock) o).hasComment()) {
				if (!removeCommentMenuInit) {
					initRemoveCommentMenu();
				}
				activeComponent = o;
				initCreateCallMenu(o, removeCommentMenu);
				// if (((RenderableBlock)o).getBlock().isProcedureParamBlock()
				// || ((RenderableBlock)o).getBlock().isDeclaration() ){
				initCreateSetterMenu(o, removeCommentMenu);
				initCreateGetterMenu(o, removeCommentMenu);
				// } else {
				// removeCommentMenu.remove(createSetterItem);
				// removeCommentMenu.remove(createGetterItem);
				// }
				return removeCommentMenu;
			} else {
				if (!addCommentMenuInit) {
					initAddCommentMenu();
				}
				activeComponent = o;
				initCreateCallMenu(o, addCommentMenu);
				// if (((RenderableBlock)o).getBlock().isProcedureParamBlock()
				// || ((RenderableBlock)o).getBlock().isDeclaration() ){
				initCreateSetterMenu(o, addCommentMenu);
				initCreateGetterMenu(o, addCommentMenu);
				// } else {
				// addCommentMenu.remove(createSetterItem);
				// addCommentMenu.remove(createGetterItem);
				// }
				return addCommentMenu;
			}

		} else if (o instanceof BlockCanvas) {
			if (!canvasMenuInit)
				initCanvasMenu();
			activeComponent = o;
			return canvasMenu;
		}
		return null;
	}

	private static void initCreateCallMenu(Object o, ContextMenu commentMenu) {
		if (((RenderableBlock) o).getBlock().isProcedureDeclBlock()) {
			if (createCallItem == null) {
				createCallItem = new MenuItem(Language.get("createCall"));
				createCallItem.setActionCommand(CREATE_CALL_BLOCK);
				createCallItem.addActionListener(createCallMenu);
			}
			commentMenu.add(createCallItem);

		} else {
			// if the Context Menu already contains "Create Call" and it has to
			// be removed
			commentMenu.remove(createCallItem);
		}

	}

	private static void initCreateSetterMenu(Object o, ContextMenu commentMenu) {
		// if (((RenderableBlock)o).getBlock().isProcedureParamBlock()||
		// ((RenderableBlock)o).getBlock().isVariableDeclBlock()){
		if (((RenderableBlock) o).getBlock().isVariableDeclBlock()
				&& ((RenderableBlock) o).getBlock().getSocketAt(0).getBlockID() != Block.NULL) {
			if (createSetterItem == null) {
				createSetterItem = new MenuItem(Language.get("setValue"));
				createSetterItem.setActionCommand(CREATE_SETTER_BLOCK);
				createSetterItem.addActionListener(createSetterMenu);
			}
			commentMenu.add(createSetterItem);

		} else {
			// if the Context Menu already contains "Create Call" and it has to
			// be removed
			commentMenu.remove(createSetterItem);
		}

	}

	private static void initCreateGetterMenu(Object o, ContextMenu commentMenu) {

		// if (((RenderableBlock)o).getBlock().isProcedureParamBlock() ||
		// ((RenderableBlock)o).getBlock().isVariableDeclBlock()){
		if ((((RenderableBlock) o).getBlock().isVariableDeclBlock() && ((RenderableBlock) o)
				.getBlock().getSocketAt(0).getBlockID() != Block.NULL)
				|| ((RenderableBlock) o).getBlock().isProcedureParamBlock()) {
			if (createGetterItem == null) {
				createGetterItem = new MenuItem(Language.get("getValue"));
				createGetterItem.setActionCommand(CREATE_GETTER_BLOCK);
				createGetterItem.addActionListener(createGetterMenu);
			}
			commentMenu.add(createGetterItem);

		} else {
			// if the Context Menu already contains "Create Call" and it has to
			// be removed
			commentMenu.remove(createGetterItem);
		}

	}

	public void actionPerformed(ActionEvent a) {
		if (a.getActionCommand() == ARRANGE_ALL_BLOCKS) {
			// notify the component that launched the context menu in the first
			// place
			if (activeComponent != null
					&& activeComponent instanceof BlockCanvas) {
				((BlockCanvas) activeComponent).arrangeAllBlocks();
			}
		} else if (a.getActionCommand() == ADD_COMMENT_BLOCK) {
			// notify the renderableblock componenet that lauched the conetxt
			// menu
			if (activeComponent != null
					&& activeComponent instanceof RenderableBlock) {
				((RenderableBlock) activeComponent).addComment();
			}
		} else if (a.getActionCommand() == REMOVE_COMMENT_BLOCK) {
			// notify the renderableblock componenet that lauched the conetxt
			// menu
			if (activeComponent != null
					&& activeComponent instanceof RenderableBlock) {
				((RenderableBlock) activeComponent).removeComment();
			}
		}
		if (a.getActionCommand() == GENERATE_JAVA_CODE) {
			if (activeComponent != null
					&& activeComponent instanceof BlockCanvas) {
				((BlockCanvas) activeComponent).generateJavaCode();
			}
		}

		if (a.getActionCommand() == CREATE_CALL_BLOCK) {
			if (activeComponent != null
					&& activeComponent instanceof RenderableBlock) {
				RenderableBlock newRB = BlockUtilities
						.getCaller((RenderableBlock) activeComponent,
								Workspace.getPage(0));
				Workspace.getPage(0)
						.addBlock(newRB);
			}
		}

		if (a.getActionCommand() == CREATE_SETTER_BLOCK) {
			// notify the component that launched the context menu in the first
			// place
			if (activeComponent != null
					&& activeComponent instanceof RenderableBlock) {
//				WorkspaceController
//						.createSetter((RenderableBlock) activeComponent);
				// ((RenderableBlock)activeComponent).createCall();

				RenderableBlock newRB = BlockUtilities
				.getSetter((RenderableBlock) activeComponent);
				Workspace.getPage(0).addBlock(newRB);

			}
		}
		if (a.getActionCommand() == CREATE_GETTER_BLOCK) {
			// notify the component that launched the context menu in the first
			// place
			if (activeComponent != null
					&& activeComponent instanceof RenderableBlock) {
//				WorkspaceController
//						.createGetter((RenderableBlock) activeComponent);
				// ((RenderableBlock)activeComponent).createCall();

					RenderableBlock newRB = BlockUtilities
					.getGetter((RenderableBlock) activeComponent);
					Workspace.getPage(0).addBlock(newRB);

		}
		}

	}
}
